package org.example;

import org.dom4j.Document;
import org.dom4j.Element;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.io.File;
import java.util.Map;

public class MyApplicationContext {
    public MyApplicationContext(String path) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
        String p = this.getClass().getClassLoader().getResource("").getPath();//注意getResource("")里面是空字符串
        Document document=BeanDefinition.analysis(p+path);
        createBean(document);
        dependencyInject(document);
    }
    public void createBean(Document document) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 获取根节点
        Element root = document.getRootElement();
        // 获取根节点中所有节点
        List<Element> elements = root.elements();
        // 便利所有节点,并执行对应set方法

        for (Element child : elements) {
            Object o=Class.forName(child.attributeValue("class")).newInstance();
            Method[] methods=o.getClass().getMethods();
            map.put(child.attributeValue("id"),o);
        }
    }
    public void dependencyInject(Document document) throws InvocationTargetException, IllegalAccessException {
        Element root = document.getRootElement();
        // 获取根节点中所有节点
        List<Element> elements = root.elements();
        // 便利所有节点,并执行对应set方法
        for (Element child : elements) {
            Object o=map.get(child.attributeValue("id"));
            Method[] methods=o.getClass().getMethods();
            if(!child.elements().isEmpty()){
                List<Element> properties = child.elements();
                for(Element prop:properties){
                    for(Method method:methods){
                        Class<?>[] getTypeParameters = method.getParameterTypes();
                        if(getTypeParameters.length!=0&&method.getName().equals("set"+prop.attributeValue("name").substring(0, 1).toUpperCase() + prop.attributeValue("name").substring(1))){
                            if(prop.attributeValue("value")==null){
                                method.invoke(o,getTypeParameters[0].cast(map.get(prop.attributeValue("ref"))));
                            }else{
                                method.invoke(o,getTypeParameters[0].cast(prop.attributeValue("value")));
                            }
                        }
                    }
                }
            }
        }
    }
    public Object getBean(String name){
        return map.get(name);
    }
    private HashMap<String,Object> map=new HashMap<>();

}
